#include "win32taskmgr.h"

CXWinTaskMgr::CXWinTaskMgr()
{
	SYSTEM_INFO info={0};
    GetSystemInfo(&info);
	_threadcount = info.dwNumberOfProcessors;
	if(_threadcount < 2)
		_threadcount = 2;
	_taskscount = 0;
	InitializeCriticalSection(&_cs);
}

int CXWinTaskMgr::Init()
{
	_mutexes = new HANDLE[_threadcount];
	_events = new HANDLE[_threadcount];
	for(int i = 0; i < _threadcount; ++i)
	{
		_mutexes[i] = CreateMutex(NULL,TRUE,NULL);
		_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL);
		IThread* th = new CXWinThread(this,_mutexes[i],_events[i]);
		_threads.push_back(th);
		ResetEvent(_events[i]);
	}
	return 0;
}

int CXWinTaskMgr::ProcessTasks(ITask** taskarray, int taskcount)
{
    _taskscount = taskcount;
    for(unsigned int i = 0; i < _taskscount; ++i)
    {
        ITask* ptask = taskarray[i];
        ITask::priority p = ptask->GetPriority();

        switch (p)
        {
            case ITask::LOW :
                _tasks_low.push_back(ptask);
                break;
            case ITask::HIGH :
                _tasks_high.push_back(ptask);
                break;
            case ITask::NORMAL :
                _tasks_normal.push_back(ptask);
                break;
        }
    }
	for(int i = 0; i < _threadcount; ++i)
		ReleaseMutex(_mutexes[i]);
	WaitForMultipleObjects(_threadcount,_events,TRUE,INFINITE);
	WaitForMultipleObjects(_threadcount,_mutexes,TRUE,INFINITE);

	return 0;
}


ITask* CXWinTaskMgr::GetTask()
{
	EnterCriticalSection(&_cs);
	ITask* task;
	if(_taskscount > 0)
	{
		if(_tasks_high.size() > 0)
		{
			task = _tasks_high[0];
			_tasks_high.pop_front();
			--_taskscount;
			LeaveCriticalSection(&_cs);
			return task;
		}else{
		if(_tasks_normal.size() > 0)
		{
			task = _tasks_normal[0];
			_tasks_normal.pop_front();
			--_taskscount;
			LeaveCriticalSection(&_cs);
			return task;
		}else{
		if(_tasks_low.size() > 0)
		{
			task = _tasks_low[0];
			_tasks_low.pop_front();
			--_taskscount;
			LeaveCriticalSection(&_cs);
			return task;
		}else{
			_taskscount = 0;
			LeaveCriticalSection(&_cs);
			return NULL;
		}}}
	}
	else
	{
		LeaveCriticalSection(&_cs);
		return NULL;
	}
}


CXWinTaskMgr::~CXWinTaskMgr()
{
	for(unsigned int i = 0; i < _threadcount; ++i)
	{
		_threads[i]->Close();
		ReleaseMutex(_mutexes[i]);
		CloseHandle(_events[i]);
		CloseHandle(_mutexes[i]);
		delete _threads[i];
	}
	delete[] _mutexes;
	delete[] _events;
	_threads.clear();
	DeleteCriticalSection(&_cs);
}